import Vue from 'vue';
import axios from 'axios'
import Store from '@/store'
import md5 from 'js-md5'
import util from '@/util'
import { random } from 'xe-utils/methods';

// 请求拦截（Header配置）
axios.interceptors.request.use(
    config => {
        let curTime = new Date()
        let token = Store.state.user.token;//Token
        let tokenExpire = new Date(Date.parse(Store.state.user.tokenexpire));//TokenExpire
        if (token && (curTime < tokenExpire && tokenExpire)) {
            // 判断是否存在token（且不过期），如果存在的话，则每个http header都加上token
            config.headers.Authorization = "Bearer " + token;
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    }
);
// 响应拦截（异常处理）
axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        // 超时请求处理
        var originalRequest = error.config;
        if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1 && !originalRequest._retry) {
            Vue.prototype.$message({
                message: '请求超时！',
                type: 'error'
            });
            originalRequest._retry = true
        }
        // 异常处理
        else if (error.response) {
            let data = error.response.data;
            //Token失效
            if (data.code === 401) {
                let curTime = new Date()
                let token = Store.state.user.token;//Token
                let tokensilde = new Date(Date.parse(Store.state.user.tokensilde));//滑动时间
                // 在用户操作的活跃期（滑动时间）内
                if (tokensilde && (curTime <= tokensilde) && token) {
                    // 直接将整个请求 return 出去，不然的话，请求会晚于当前请求，无法达到刷新操作 
                    return refreshToken({ token: token }).then((res) => {
                        if (res.code === 200) {
                            Store.commit("SET_TOKENREFERENCE", { token: res.data.token, tokenexpire: res.data.expires_in });

                            error.config.__isRetryRequest = true;
                            error.config.headers.Authorization = 'Bearer ' + res.data.token;
                            // error.config 包含了当前请求的所有信息
                            return axios(error.config);
                        } else {
                            // 刷新token失败 清除token信息并跳转到登录页面
                            Store.dispatch('Logout');
                        }
                    });
                } else {
                    // 返回 401，并且不知用户操作活跃期内 清除token信息并跳转到登录页面
                    Store.dispatch('Logout');
                }
            }
            //其余异常
            else {
                Vue.prototype.$message({
                    message: data.code === undefined ? "接口通讯异常，请检查浏览器控制台！" : data.msg,
                    type: 'warning'
                });
            }
        }
        // 接口服务器未响应
        else {
            Vue.prototype.$message({
                message: '服务器未响应，请求发起失败！',
                type: 'error'
            });
        }
        Store.commit("SET_ISLOADING", false);
        //this.$XModal.close(); //全局关闭动态的活动窗口
        return Promise.reject(error); // 返回接口返回的错误信息
    }
);

//参数添加安全校验
export const securityParams = params => {
    const timestamp = Math.round(new Date() / 1000);
    const nonce = random(1234, 4321);
    var security = {
        appid: Store.state.app.appid,
        timestamp: timestamp,
        nonce: nonce,
        signature: md5([Store.state.app.appsecret, timestamp, nonce].sort().join(''))
    }
    return Object.assign(security, params);
}
//JWT滑动授权刷新（刷新JWT）
const refreshToken = params => {
    return axios.post(`${Store.state.app.root}api/login/RefreshToken`, securityParams(params)).then(res => res.data);
};



// 锁屏实例
var loading;
// 自定义判断元素类型JS
const toType = function (obj) {
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
};
// 参数过滤函数
const filterNull = function (o) {
    for (var key in o) {
        const type = toType(o[key]);
        if (o[key] === null) {
            delete o[key];
        }
        if (type === 'string') {
            o[key] = o[key].trim()
        } else if (type === 'object') {
            o[key] = filterNull(o[key])
        } else if (type === 'array') {
            o[key] = filterNull(o[key])
        }
    }
    return o
};
// Axios网络请求
const apiAxios = function (method, url, params) {
    if (params) {
        params = filterNull(params)
    }
    return new Promise((resolve, reject) => {
        axios({
            method: method,
            url: url,
            data: method === 'POST' || method === 'PUT' ? params : null,
            params: method === 'GET' || method === 'DELETE' ? params : null,
            baseURL: Store.state.app.root,
            withCredentials: false,
            timeout: 300000
        })
            .then(res => {
                if (res.data.code === 200) {
                    //增、删、改 操作，成功返回提示
                    if (method === 'PUT') {
                        Vue.prototype.$message({
                            message: res.data.msg,
                            type: 'success'
                        });
                        //关闭锁屏
                        loading.close();
                    }
                    resolve(res.data.data);
                }
            })
            .catch(err => {
                if (method === 'PUT') loading.close(); //关闭锁屏
                reject(err.data);
            })
    })
};
// 封装的Axios网络请求
export const http = {
    //获取
    get: function (url, params) {
        return apiAxios('GET', url, params)
    },
    //获取/提交
    post: function (url, params) {
        return apiAxios('POST', url, params)
    },
    //提交（锁屏 + 成功提示）
    put: function (url, params) {
        //锁屏
        loading = Vue.prototype.$loading({
            lock: true,
            text: "数据提交中...",
            spinner: "el-icon-loading",
            background: "rgba(0, 0, 0, 0.7)"
        });
        return apiAxios('PUT', url, params)
    },
    delete: function (url, params) {
        return apiAxios('DELETE', url, params)
    },
    //获取树型数据
    getTree: function (url, params, removeId) {
        return new Promise((resolve, reject) => {
            apiAxios('GET', url, params).then((res) => {
                if(removeId){
                    resolve(util.removeChildren(res, removeId));
                }else{
                    resolve(util.removeChildren(res));
                }
            })
        }) 
    },
}